#pragma once
namespace DinoMath
{
	class vec3
	{
	public:

		vec3() {}
		vec3(float num) { x = num; y = num; z = num; }
		vec3(float _x, float _y, float _z) { x = _x; y = _y; z = _z; }
		

		// OPERATORS
		// typecast operators
		operator float * () {
			return _array;
		}

		operator const float * () const {
			return _array;
		}

		// indexing operators
		float &operator [] (int i) 
		{
			return _array[i];
		}

		const float &operator [] (int i) const
		{
			return _array[i];
		}

		// unary ops
		inline vec3 & operator *=
		(
			float const & s
		)
		{
			this->x *= s;
			this->y *= s;
			this->z *= s;
			return *this;
		}

		inline vec3 & operator*=
		(
			vec3 const & v
		)
		{
			this->x *= v.x;
			this->y *= v.y;
			this->z *= v.z;
			return *this;
		}

		inline vec3 & operator+=
		(
			float const & s
		)
		{
			this->x += s;
			this->y += s;
			this->z += s;
			return *this;
		}

		inline vec3 & operator+=
		(
			vec3 const & v
		)
		{
			this->x += v.x;
			this->y += v.y;
			this->z += v.z;
			return *this;
		}

		// binary ops
		//template <typename T> 
		friend inline vec3 operator+
		(
			vec3 const & v, 
			float const & s
		)
		{
			return vec3(
				v.x + float(s),
				v.y + float(s),
				v.z + float(s));
		}

		//template <typename T> 
		friend inline vec3 operator+ 
		(
			float const & s, 
			vec3 const & v
		)
		{
			return vec3(
				float(s) + v.x,
				float(s) + v.y,
				float(s) + v.z);
		}

		//template <typename T> 
		friend inline vec3 operator+ 
		(
			vec3 const & v1, 
			vec3 const & v2
		)
		{
			return vec3(
				v1.x + v2.x,
				v1.y + v2.y,
				v1.z + v2.z);
		}

		//operator*
		//template <typename T> 
		friend inline vec3 operator*
		(
			vec3 const & v, 
			float const & s
		)
		{
			return vec3(
				v.x * float(s),
				v.y * float(s),
				v.z * float(s));
		}

		//template <typename T> 
		friend inline vec3 operator* 
		(
			float const & s, 
			vec3 const & v
		)
		{
			return vec3(
				float(s) * v.x,
				float(s) * v.y,
				float(s) * v.z);
		}

		//template <typename T> 
		friend inline vec3 operator* 
		(
			vec3 const & v1, 
			vec3 const & v2
		)
		{
			return vec3(
				v1.x * float(v2.x),
				v1.y * float(v2.y),
				v1.z * float(v2.z));
		}

		//operator-
		//template <typename T> 
		friend inline vec3 operator- 
		(
			vec3 const & v, 
			float const & s
		)
		{
			return vec3(
				v.x - float(s),
				v.y - float(s),
				v.z - float(s));
		}

		//template <typename T> 
		friend inline vec3 operator- 
		(
			float const & s, 
			vec3 const & v
		)
		{
			return vec3(
				float(s) - v.x,
				float(s) - v.y,
				float(s) - v.z);
		}

		//template <typename T> 
		friend inline vec3 operator- 
		(
			vec3 const & v1, 
			vec3 const & v2
		)
		{
			return vec3(
				v1.x - float(v2.x),
				v1.y - float(v2.y),
				v1.z - float(v2.z));
		}


		// UNION ACCESSOR
		union
		{
			float _array[3];
			struct
			{
				float x;
				float y;
				float z;
			};
		};
	};


	//===================================================================
	class Vec2
	{
	public:

		Vec2() {}
		Vec2(float num) { x = num; y = num; }
		Vec2(float _x, float _y) { x = _x; y = _y; }

		// OPERATORS
		// typecast operators
		operator float * () {
			return _array;
		}

		operator const float * () const {
			return _array;
		}

		// indexing operators
		float &operator [] (int i) 
		{
			return _array[i];
		}

		const float &operator [] (int i) const
		{
			return _array[i];
		}

		// UNION ACCESSOR
		union
		{
			float _array[2];
			struct
			{
				float x;
				float y;
			};
		};
	};
}

